import {
  Component,
  ElementRef,
  EventEmitter,
  Input,
  OnInit,
  Output,
  ViewChild,
  HostListener,
  NgZone,
  SimpleChanges
} from '@angular/core';
import { HttpService } from "../../../http/http.service";
import { Observable } from "rxjs";
import { LocalStorage } from "../../../utils/localstorage";
import { NotifyService } from "../../../utils/notify.service";

@Component({
  selector: 'meta-table',
  templateUrl: './meta-table.component.html',
  styleUrls: ['./meta-table.component.styl']
})
export class MetaTableComponent implements OnInit {

  constructor(private http: HttpService, private zone: NgZone, private notify: NotifyService) {
  }

  ngOnInit(): void {
    this.setScroll();
    this.search();
  }

  ngOnChanges(changes: SimpleChanges) {
    let btns = [];
    this.lineBtnGroup.forEach((itm) => {
      if (itm.id) {
        if (LocalStorage.isButton(itm.id)) {
          btns.push(itm);
        }
      } else {
        btns.push(itm);
      }
    });
    this.lineBtnGroup = btns;
  }

  @ViewChild('divTable', { static: true }) divTable: ElementRef;

  @Input() url: string;              // 查询URL
  @Input() searchForm: any = {};     // 查询条件
  @Input() columns = [];             // 表格列信息
  @Input() showCheckbox = false;     // 是否显示checkBox
  @Input() singleCheck = false;      // 是否单选
  @Input() lineBtnGroup = [];        // 行操作按钮
  @Input() lineBtnWidth: number = 100;   // 行操作按钮宽度
  @Output() lineBtnClick = new EventEmitter<object>(); // 行操作按钮点击
  @Output() lineRadioClick = new EventEmitter<object>(); // 行操作按钮点击
  @Output() inputChange = new EventEmitter<object>(); // 单元格输入改变
  @Output() suffixClick = new EventEmitter<object>(); // 单元格图标点击
  @Output() stepClick = new EventEmitter<object>(); // 单元格步骤点击
  @Output() backClick = new EventEmitter<object>(); // 单元格背景点击
  @Output() onSort = new EventEmitter<object>();    // 排序
  @Input() height: number = null;      // 表高
  @Input() searchHeight: number = 90;  // 搜索框高度。必须给，不然样式会有问题
  @Input() parentIndex: number = 0;    // 在外层循环metatable时，传入当前metatable所有的索引。目前用于输入框回车光标下移动
  scroll = { x: '1000px', y: '0px' };  // 表的宽和高

  total = 0;
  pageIndex = 1;
  @Input() pageSize = 10;
  @Input() showPagination = true;

  @Input() tableData = [];

  allChecked = false;
  checkedMap: { [key: number]: boolean } = {};
  checkedRows = [];
  @Output() selectRows = new EventEmitter<object>();

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    this.zone.run(() => {
      this.setHeightScroll();
    });
  }

  setHeightScroll(): void {
    let pNode = this.divTable.nativeElement.offsetParent;
    if (!pNode) {
      return;
    }

    let maxCount = 1;
    while (true) {
      let tagName = pNode.tagName.toLowerCase();
      if (tagName === "body") {
        break;
      }
      pNode = pNode.offsetParent;
      maxCount++;
      //避免死循环
      if (maxCount > 200) {
        break;
      }
    }
    let allHeight = pNode.offsetHeight;
    this.scroll.y = (allHeight - (215 + this.searchHeight)) + 'px';
  }

  setWidthScroll(): void {
    let width = 0;
    for (let idx in this.columns) {
      width += this.columns[idx].width ? this.columns[idx].width : 100;
    }

    if (this.showCheckbox) {
      width += 50;
    }
    if (this.lineBtnGroup.length > 0) {
      width += this.lineBtnWidth;
    }

    this.scroll.x = width + 'px';
  }

  /**
   * 设置表的宽度和高度
   */
  setScroll(): void {
    this.setWidthScroll();

    if (this.height != null) {
      if (this.height < 0) {
        delete this.scroll.y;
      } else {
        this.scroll.y = this.height + 'px';
      }
    } else {
      this.setHeightScroll();
    }
  }

  onSearch(): void {
    this.pageIndex = 1;
    this.search();
  }

  /**
   * 此方法只针对项目评测光标下移使用。
   * 具有强大的针对性，小心修改
   * @param col
   * @param idx
   */
  onKeyEnter(col, idx) {
    if (col.inputType && col.inputType.keyEnter) {
      col.inputType.keyEnter(col.item, this.parentIndex, idx);
    }
  }

  /**
   * 带有返回数据的查询
   */
  onSearchWithData(): Observable<any> {
    let obs: Observable<any> = Observable.create(observer => {
      let para = {
        page: this.pageIndex,
        limit: this.pageSize,
        params: encodeURI(JSON.stringify(this.searchForm))
      };

      this.http.get(this.url, para).subscribe(res => {
        this.tableData = res.data;
        this.total = res.recordCount;
        this.checkInit();
        observer.next(res.data);
      });
    });

    return obs;
  }

  search(): void {
    if (!this.url) {
      return;
    }

    let para = {
      page: this.pageIndex,
      limit: this.pageSize,
      params: encodeURI(JSON.stringify(this.searchForm))
    };

    this.http.get(this.url, para).subscribe(res => {
      if (res.err == '0') {
        this.tableData = res.data;
        this.total = res.recordCount;
        this.checkInit();
      } else {
        this.notify.error(res.errMsg).subscribe();
      }
    });
  }

  /**
   * 行操作按钮点击
   * @param btnId 按钮ID
   * @param rowData 行数据
   */
  onLineBtnClick(btn, rowData: any): void {
    if (btn.click) {
      btn.click(rowData);
    } else {
      this.lineBtnClick.emit({ 'btnId': btn.id, 'rowData': rowData });
    }
  }

  /**
   * 输入框值改变
   * @param item 列名称（英文）
   * @param value 改变后的值
   * @param rowData 行数据
   */
  onInputChange(item, value, rowData) {
    this.inputChange.emit({ 'item': item, 'rowData': rowData });
  }

  /**
   * 单元格图表点击
   * @param item 列名称（英文）
   * @param rowData 行数据
   */
  onSuffixClick(item, rowData) {
    this.suffixClick.emit({ 'item': item, 'rowData': rowData });
  }

  /**
   * 步骤条点击
   * @param item 列名称（英文）
   * @param rowData 行数据
   * @param step 步骤
   * @param stepIndex 步骤索引
   * @constructor
   */
  onStepClick(item, rowData, step, stepIndex) {
    this.stepClick.emit({ 'item': item, 'rowData': rowData, 'step': step, 'stepIndex': stepIndex });
  }

  /**
   * 问卷调查点击
   * @param item 列名称（英文）
   * @param rowData 行数据
   * @param step 步骤
   * @param stepIndex 步骤索引
   * @constructor
   */
  onQuestionClick(item, rowData) {
    this.backClick.emit({ 'item': item, 'rowData': rowData });
  }

  onRadioClick(rowData, item, radioValue): void {
    this.lineRadioClick.emit({ 'rowData': rowData, item: item, radioValue: radioValue });
  }

  /**
   *checkBox初始化
   */
  checkInit(): void {
    this.allChecked = false;
    this.checkedMap = {};
    this.checkAll(false);
  }

  /**
   * checkBox全选或全部取消
   * @param value true：全选，false：全部取消
   */
  checkAll(value: boolean): void {
    this.allChecked = value;

    for (let idx in this.tableData) {
      this.checkedMap[idx] = value;
    }

    this.setCheckedRows();
  }

  /**
   * checkBox单行操作
   */
  checkOne(value, idx): void {
    // 单选时，其他行清除选中
    if (this.singleCheck) {
      for (let key in this.checkedMap) {
        this.checkedMap[key] = false;
      }
      this.checkedMap[idx] = value;
    }

    let flg = true;
    for (let key in this.checkedMap) {
      if (!this.checkedMap[key]) {
        flg = false;
        break;
      }
    }
    this.allChecked = flg;

    this.setCheckedRows();
  }

  setCheckedRows(): void {
    this.checkedRows = [];
    for (let key in this.checkedMap) {
      if (this.checkedMap[key]) {
        this.checkedRows.push(this.tableData[key]);
      }
    }

    this.selectRows.emit(this.checkedRows);
  }

  public getData() {
    return this.tableData;
  }

  public setData(data) {
    //设置新的数据后需要重置
    this.checkInit();
    this.tableData = data;
  }

  sort(sort: { key: string; value: string }) {
    this.searchForm.sortKey = sort.key;
    if (sort.value == 'ascend') {
      this.searchForm.sortValue = 'ASC';
    } else if (sort.value == 'descend') {
      this.searchForm.sortValue = 'DESC';
    } else {
      this.searchForm.sortValue = '';
    }

    this.onSort.emit(sort);
    this.search();
  }
}

